package chixing.day17.reflect;

import javax.naming.Name;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


/**
 * reflect 反射
 * 类全名： 包名.类名
 * chixing.day17.reflect.Recorde 加载在jvm中
 * 类的所有结构{类名，父类名，父类，构造函数，属性，方法...}
 * interface 接口
 * super class 父类
 * constructor 构造函数
 * Field 字段
 * Method 方法
 * Modified 修饰符
 */
public class ReflectDemo {
    public static void main(String[] args) {

        Class<Record> clazz = Record.class;
        String className = clazz.getName();
        System.out.println("类名：" + className);//类名：chixing.day17.reflect.Record

        Class<? super Record> superClass = clazz.getSuperclass();
        System.out.println("父类名：" + superClass);//父类名：class java.lang.Object

        System.out.println("父接口----------------");
        Class<?>[] interfaces = clazz.getInterfaces();//获取该类的所有接口
        for (Class c :interfaces){
            System.out.println(c);
        }

        //获取所有方法（对象）,只能获取public修饰的
        Method[] methods = clazz.getMethods();
        for (Method method:methods){
            //方法的方法名
            String methodName = method.getName();
            System.out.println("1.方法名：" + methodName);
            //获取方法修饰符，修饰符用十六进制表示的，返回的方法修饰符是将他们对应的十六进制的数相加
            int modifiers = method.getModifiers();
            System.out.println("2.方法的修饰符" + modifiers);// public(1) + static(8) + final (16)
            //返回值类型
            Class<?> returnType = method.getReturnType();
            System.out.println("3.返回值类型" + returnType);
            //方法的参数列表
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (Class type:parameterTypes){
                System.out.println("4.方法的参数列表类型"+type);
            }
            System.out.println("------------------");

            //通过反射 调用 fun0()(.....)
            //返回值 = fun0().invoke(对象名，参数列表)

            if (methodName.equals("fun0")){
                // 反射的语法创建对象  MyRecord record = clazz.getDeclaredConstructor().newInstance();
                Record record = null;
                try {
                    record = clazz.getDeclaredConstructor().newInstance();
                } catch (InstantiationException e) {
                    throw new RuntimeException(e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                } catch (InvocationTargetException e) {
                    throw new RuntimeException(e);
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException(e);
                }
                try {
                    //通过反射调用方法
                    //invoke 被调用
                    Object returnValue = method.invoke(record, 10, 9.9f);
                    System.out.println("fun0的返回值是：" + returnValue);
                } catch (IllegalAccessException e) {//非法访问（访问权限不够）
                    throw new RuntimeException(e);
                } catch (InvocationTargetException e) {//invocate 调用目标非法
                    throw new RuntimeException(e);
                }

                Field[] declaredFields = clazz.getDeclaredFields();

                for (Field field:declaredFields){
                    System.out.println("对象的字段名：" + field);
                }

            }
            //获取指定的方法
            try {
                Method method1 = clazz.getMethod("setTransactionAmount", double.class);//方法名，参数列表
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
            System.out.println("--------------constructor--------------------");
            Record record1 = null;
            Record record2 = null;
            try {//相当于无参构造，Record record = new Record()
                record1 = clazz.getConstructor().newInstance();
                //相当于有参构造
                record2 = clazz.getDeclaredConstructor(String.class,String.class).newInstance("110011","allen");
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
            try {
                Field field  = clazz.getField("userName");
                Class<?> type = field.getType();
                System.out.println("userName 字段的类型：" + type);
                int modifiers1 = field.getModifiers();
                System.out.println("userName 字段的修饰符:" + modifiers1);
                field.set(record1,"bill");//给record1的userName字段赋值为“bill”
                Object name = field.get(record1);
                System.out.println("userName 赋值后的值是："+ name);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }


        }

    }
}
